﻿using FySystem.Data.OrmA.Db;
using FySystem.Data.OrmA.Formatter;
using FySystem.Data.OrmA.Reflection;
using FySystem.IO;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;

namespace FySystem.Data.OrmA.Resolvers.Lambdas
{
    public class DbSelector<T>
    {
        internal List<DbSelectExpression<T>> Opers = new List<DbSelectExpression<T>>();
        internal DBSession DbSession;

        internal bool Flag = false;

        internal DbSelector(DBSession session)
        {
            DbSession = session;
            Opers.Add(new DbSelectExpression<T>(DbKeywords.SELECT));
        }

        internal DbSelector(DBSession session, Expression<Func<T,object>> expression)
        {
            DbSession = session;
            Opers.Add(new DbSelectExpression<T>(DbKeywords.SELECT, expression));
        }

        public DbSelector<T> Max(Expression<Func<T,object>> expression)
        {
            AddOper(DbKeywords.MAX, new DbSelectExpression<T>(DbKeywords.MAX, expression));
            Flag = true;
            return this;
        }

        public DbSelector<T> Min(Expression<Func<T, object>> expression)
        {
            AddOper(DbKeywords.MIN, new DbSelectExpression<T>(DbKeywords.MIN, expression));
            Flag = true;
            return this;
        }

        public DbSelector<T> Avg(Expression<Func<T, object>> expression)
        {
            AddOper(DbKeywords.AVG, new DbSelectExpression<T>(DbKeywords.AVG, expression));
            Flag = true;
            return this;
        }

        public DbSelector<T> Sum(Expression<Func<T, object>> expression)
        {
            AddOper(DbKeywords.SUM, new DbSelectExpression<T>(DbKeywords.SUM, expression));
            Flag = true;
            return this;
        }

        //public DbSelector<T> Count()
        //{
        //    AddOper(DbKeywords.COUNT, new DbSelectExpression<T>(DbKeywords.COUNT));
        //    Flag = true;
        //    return this;
        //}

        public DbSelector<T> NVL(Expression<Func<T,object>> exception,object destValue)
        {
            AddOper(DbKeywords.NVL, new DbSelectExpression<T>(DbKeywords.NVL, exception, new object[] { destValue }));
            Flag = true;
            return this;
        }

        public DbSelector<T> Where(Expression<Func<T,bool>> expression)
        {
            AddOper(DbKeywords.WHERE, new DbSelectExpression<T>(DbKeywords.WHERE, expression));
            return this;
        }

        public DbSelector<T> Orderby(Expression<Func<T,object>> expression, bool isASC=true)
        {
            AddOper(DbKeywords.ORDERBY, new DbSelectExpression<T>(DbKeywords.ORDERBY, expression, new object[] { isASC }));
            return this;
        }

        public DbSelector<T> GroupBy(Expression<Func<T, object>> expression)
        {
            AddOper(DbKeywords.GROUPBY, new DbSelectExpression<T>(DbKeywords.GROUPBY, expression));
            return this;
        }

        //public DbSelector<T> Limit(params int[] limitValue)
        //{
        //    DbSelectExpression<T> exper = new DbSelectExpression<T>(DbKeywords.LIMIT);
        //    if(limitValue!=null)
        //    {
        //        exper.Parameters = new object[limitValue.Length];
        //        for (int i = 0; i < exper.Parameters.Length; i++)
        //            exper.Parameters[i] = limitValue[i];
        //    }
        //    AddOper(DbKeywords.LIMIT, exper);
        //    return this;
        //}

        public T ToSingle()
        {
            try
            {
                ReflectionInfo reflectionInfo = ReflectionManager.ReflectionModel<T>();
                FormatResult fmtSQL = LambdaSQLCreater.CreateSQL(DbSession, reflectionInfo, Opers, Flag, false);
                return DataCopy.CopyDataToSingle<T>(reflectionInfo, DbSession.DbHelper, fmtSQL);
            }
            catch (Exception)
            {
                throw;
            }
        }

        public CSon ToSingleC()
        {
            try
            {
                ReflectionInfo reflectionInfo = ReflectionManager.ReflectionModel<T>();
                FormatResult fmtSQL = LambdaSQLCreater.CreateSQL(DbSession, reflectionInfo, Opers, Flag, false);
                return DataCopy.CopyDataToSingleC(DbSession.DbHelper, fmtSQL);
            }
            catch (Exception)
            {
                throw;
            }
        }

        public List<T> ToList()
        {
            try
            {
                ReflectionInfo reflectionInfo = ReflectionManager.ReflectionModel<T>();
                FormatResult fmtSQL = LambdaSQLCreater.CreateSQL(DbSession, reflectionInfo, Opers, Flag, true);
                return DataCopy.CopyDataToList<T>(reflectionInfo, DbSession.DbHelper, fmtSQL);
            }
            catch (Exception)
            {
                throw;
            }
        }

        public List<CSon> ToListC()
        {
            try
            {
                ReflectionInfo reflectionInfo = ReflectionManager.ReflectionModel<T>();
                FormatResult fmtSQL = LambdaSQLCreater.CreateSQL(DbSession, reflectionInfo, Opers, Flag, true);
                return DataCopy.CopyDataToListC(DbSession.DbHelper, fmtSQL);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void AddOper(DbKeywords dbKeywords, DbSelectExpression<T> oper)
        {
            if (oper != null)
                Opers.Add(oper);
        }
    }
}
